﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AIStudio.Wpf.DiagramDesigner
{
    /// <summary>
    /// LineControl.xaml 的交互逻辑
    /// </summary>
    public partial class LineControl : UserControl
    {
        public LineControl()
        {
            InitializeComponent();

            this.Loaded += PathAnimation_Loaded;
            this.Unloaded += LineControl_Unloaded;
        }

        private void LineControl_Unloaded(object sender, RoutedEventArgs e)
        {
            if (this.DataContext is ConnectionViewModel connector && connector.AnimationViewModel != null)
            {
                connector.AnimationViewModel.PropertyChanged -= Connector_PropertyChanged;
                connector.PropertyChanged -= Connector_PropertyChanged;
            }
            _story?.Stop();
        }

        private async void PathAnimation_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.DataContext is ConnectionViewModel connector && connector.AnimationViewModel != null)
            {
                connector.AnimationViewModel.PropertyChanged -= Connector_PropertyChanged;
                connector.AnimationViewModel.PropertyChanged += Connector_PropertyChanged;
                connector.PropertyChanged -= Connector_PropertyChanged;
                connector.PropertyChanged += Connector_PropertyChanged;
            }
            this.ball.Visibility = Visibility.Collapsed;
            await DoAnimation();
        }

        private async void Connector_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case nameof(AnimationViewModel.Animation):
                case nameof(AnimationViewModel.Duration):
                case "PathGeneratorResult":
                    await DoAnimation();
                    break;
                case nameof(AnimationViewModel.Start):
                    await Application.Current?.Dispatcher.Invoke(async () => {
                        await DoAnimation();
                    });
                    break;

            }
        }

        private async Task DoAnimation()
        {
            if (this.DataContext is ConnectionViewModel connector && connector.IsFullConnection)
            {
                if (connector.AnimationViewModel.Repeat == false)
                {
                    if (connector.AnimationViewModel.Start == false || connector.AnimationViewModel.Completed == 1)
                    {
                        return;
                    }
                    connector.AnimationViewModel.Completed = 1;
                    connector.AnimationViewModel.Start = false;
                }

                await System.Threading.Tasks.Task.Delay(10);
                switch (connector.AnimationViewModel.Animation)
                {
                    case LineAnimation.None:
                        _story?.Stop(this);
                        ball.Visibility = Visibility.Collapsed;
                        break;
                    case LineAnimation.PathAnimation:
                        if (connector.ColorViewModel.FillColor.BrushType == BrushType.SolidColorBrush && connector.ColorViewModel.FillColor.Color == Colors.White)
                        {
                            connector.ColorViewModel.FillColor.Color = Colors.Red;
                        }
                        PathAnimation(connector.AnimationViewModel);
                        break;
                    case LineAnimation.DashAnimation:
                        if (connector.ColorViewModel.LineDashStyle == LineDashStyle.None)
                        {
                            connector.ColorViewModel.LineDashStyle = LineDashStyle.Dash1;
                        }
                        DashAnimation(connector.AnimationViewModel);
                        break;
                }
            }
        }

        Storyboard _story;

        private void PathAnimation(IAnimationViewModel animationViewModel)
        {
            this.ball.Visibility = Visibility.Visible;

            Canvas.SetTop(this.ball, -this.ball.ActualHeight / 2);
            Canvas.SetLeft(this.ball, -this.ball.ActualWidth / 2);

            this.ball.RenderTransformOrigin = new Point(0.5, 0.5);

            TranslateTransform translate = new TranslateTransform();
            RotateTransform rotate = new RotateTransform();
            TransformGroup group = new TransformGroup();
            group.Children.Add(rotate);//先旋转
            group.Children.Add(translate);//再平移
            this.ball.RenderTransform = group;

            NameScope.SetNameScope(this, new NameScope());
            this.RegisterName("translate", translate);
            this.RegisterName("rotate", rotate);

            DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
            animationX.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
            animationX.Source = PathAnimationSource.X;
            animationX.Duration = new Duration(TimeSpan.FromSeconds(animationViewModel.Duration));

            DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath();
            animationY.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
            animationY.Source = PathAnimationSource.Y;
            animationY.Duration = animationX.Duration;

            DoubleAnimationUsingPath animationAngle = new DoubleAnimationUsingPath();
            animationAngle.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
            animationAngle.Source = PathAnimationSource.Angle;
            animationAngle.Duration = animationX.Duration;

            _story?.Stop(this);
            _story = new Storyboard();
            //_story.RepeatBehavior = RepeatBehavior.Forever;
            //story.AutoReverse = true;
            _story.Children.Add(animationX);
            _story.Children.Add(animationY);
            _story.Children.Add(animationAngle);
            _story.Completed += (s, d) => {
                if (animationViewModel.Repeat)
                {
                    _story.Begin(this, true);
                }
                else
                {
                    this.ball.Visibility = Visibility.Collapsed;
                    animationViewModel.Completed = 100;
                }
            };
            Storyboard.SetTargetName(animationX, "translate");
            Storyboard.SetTargetName(animationY, "translate");
            Storyboard.SetTargetName(animationAngle, "rotate");
            Storyboard.SetTargetProperty(animationX, new PropertyPath(TranslateTransform.XProperty));
            Storyboard.SetTargetProperty(animationY, new PropertyPath(TranslateTransform.YProperty));
            Storyboard.SetTargetProperty(animationAngle, new PropertyPath(RotateTransform.AngleProperty));

            _story.Begin(this, true);

        }

        private void DashAnimation(IAnimationViewModel animationViewModel)
        {
            this.ball.Visibility = Visibility.Collapsed;


            var animation = new DoubleAnimation(0, -10, new Duration(TimeSpan.FromSeconds(animationViewModel.Duration)))
            {
                RepeatBehavior = RepeatBehavior.Forever,
            };
            Storyboard.SetTargetProperty(animation, new PropertyPath("StrokeDashOffset"));
            Storyboard.SetTarget(animation, this.line);

            _story?.Stop(this);
            _story = new Storyboard();
            _story.RepeatBehavior = RepeatBehavior.Forever;
            _story.Children.Add(animation);
            _story.Completed += (s, d) => {
                if (animationViewModel.Repeat)
                {
                    _story.Begin(this, true);
                }
                else
                {
                    this.ball.Visibility = Visibility.Collapsed;
                    animationViewModel.Completed = 100;
                }
            };
            _story.Begin(this, true);
        }

    }
}
